import { action, computed, flow, makeObservable, observable, runInAction, when } from 'mobx';
import { storageToken } from 'Configs/common';
import LoginStore from 'Core/LoginStore';
import AuthStore from 'Core/AuthStore';
import { ActionRequestCanceler } from 'Typings/common';
import { auth } from 'Apis';
import { AxiosResponse } from 'axios';
import request from 'Utils/request';

export class RootStore {
    @observable initialDataRequesting = false;

    @observable.ref getInitialDataCanceler: ActionRequestCanceler = () => {};

    @observable getAuthPublicKeyRequesting = false;

    @observable.ref getAuthPublicKeyCanceler: ActionRequestCanceler = () => {};

    @observable id = '';

    @computed get token() {
        return this.authStore.token ?? undefined;
    }

    /* frame begin */
    @observable loginStore: LoginStore = new LoginStore();

    @observable authStore: AuthStore = new AuthStore();

    constructor() {
        makeObservable(this);

        this.authStore.setToken(localStorage.getItem(storageToken) ?? undefined);
        this.authStore.setDefaultCreateFormData(this.authStore.getInfoFromLocalStorage());

        when(
            () => !this.token,
            () => {
                this.authStore.destory();
            },
        );
    }

    @action destory: NoneParamsAndReturnFuc = () => {
        this.initialDataRequesting = false;
        this.getInitialDataCanceler = () => {};

        this.getAuthPublicKeyRequesting = false;
        this.getAuthPublicKeyCanceler = () => {};

        this.id = '';
        this.authStore.destory();
    };

    @action changeFieldValue: ChangeFieldValue<this> = (field, value) => {
        this[field] = value;
    };

    @action getInitialData = flow(function* getInitialData(this: RootStore) {
        if (!this) return;

        this.initialDataRequesting = true;
        try {
            const { apiGetLoginInfo } = auth;

            const responseData: AxiosResponse<CommonSysReponse<{ id: SysId }>> = yield request(apiGetLoginInfo, {
                canceler: canceler => {
                    this.getInitialDataCanceler = canceler;
                },
            });

            if (responseData?.data) {
                const { code, data } = responseData.data;

                if (code === 200) {
                    runInAction(() => {
                        this.id = data.id;
                        this.initialDataRequesting = false;
                    });
                }
            } else {
                throw new Error('no data');
            }
        } catch (error) {
            runInAction(() => {
                this.initialDataRequesting = false;
            });
        }
    });
}

export default new RootStore();
